import { ContainerUsualProp } from '../../common/property/container-property-config';
import { ElementPropertyConfig } from '@farris/ide-property-panel';
import { EventsEditorFuncUtils } from '../../../../utils/events-editor-func';
import { FormPropertyChangeObject } from '../../../../entity/property-change-entity';
import { cloneDeep, set } from 'lodash-es';
export class ComponentProp extends ContainerUsualProp {

    getPropConfig(propertyData: any): ElementPropertyConfig[] {

        const propertyConfig = [];

        // 基本信息属性
        const basicPropConfig = this.getBasicPropConfig(propertyData, this.viewModelId);
        propertyConfig.push(basicPropConfig);

        // 外观属性
        const appearancePropConfig = this.getAppearancePropConfig(propertyData, this.viewModelId);
        propertyConfig.push(appearancePropConfig);

        // 行为属性
        const behaviorPropConfig = this.getBehaviorPropConfig(propertyData, this.viewModelId);
        propertyConfig.push(behaviorPropConfig);

        // 事件属性
        const eventPropConfig = this.getEventPropertyConfig(propertyData, this.viewModelId);
        propertyConfig.push(eventPropConfig);

        return propertyConfig;
    }

    private getAppearancePropConfig(propertyData: any, viewModelId: string): ElementPropertyConfig {
        const self = this;
        const props = this.getCommonAppearanceProperties();

        const propData = cloneDeep(propertyData);
        // 【模型名称】是保存到ViewModel上的，不是保存到Component上，所以这里复制一份属性值
        const vm = this.domService.getViewModelById(viewModelId);
        propData.name = vm ? vm.name : null;

        props.push(
            {
                propertyID: 'name',
                propertyName: '组件名称',
                propertyType: 'string'
            }
        );
        return {
            categoryId: 'appearance',
            categoryName: '外观',
            propertyData: propData,
            enableCascade: true,
            properties: props,
            setPropertyRelates(changeObject: FormPropertyChangeObject) {

                if (!changeObject) {
                    return;
                }
                switch (changeObject.propertyID) {
                    case 'name': {
                        self.syncChangesToViewModel(viewModelId, { name: changeObject.propertyValue });
                        break;
                    }

                    default: {
                        // 将属性值同步到Component属性上
                        const propPath = changeObject.parentPropertyID ? changeObject.parentPropertyID + '.' + [changeObject.propertyID] : [changeObject.propertyID];
                        set(propertyData, propPath, changeObject.propertyValue);
                        break;
                    }
                }
            }
        };
    }


    private getBehaviorPropConfig(propertyData: any, viewModelId: string): ElementPropertyConfig {
        const self = this;
        const propData = cloneDeep(propertyData);
        const visibleProp = this.getVisiblePropertyEntity(propertyData, viewModelId);

        // 是否启用校验是保存到ViewModel上的，不是保存到Component上，所以这里复制一份属性值
        const vm = this.domService.getViewModelById(viewModelId);
        propData.enableValidation = vm ? vm.enableValidation : null;

        return {
            categoryId: 'behavior',
            categoryName: '行为',
            propertyData: propData,
            enableCascade: true,
            properties: [
                visibleProp,
                {
                    propertyID: 'enableValidation',
                    propertyName: '启用校验',
                    propertyType: 'select',
                    description: '运行时组件是否启用校验',
                    iterator: [
                        { key: true, value: '是' },
                        { key: false, value: '否' }
                    ],
                    visible: !!vm.parent // 根组件不支持启用校验属性
                }
            ],
            setPropertyRelates(changeObject: FormPropertyChangeObject) {

                if (!changeObject) {
                    return;
                }
                switch (changeObject.propertyID) {
                    case 'visible': {
                        // 将属性值同步到Component属性上
                        propertyData.visible = changeObject.propertyValue;
                        break;
                    }
                    case 'enableValidation': {
                        self.syncChangesToViewModel(viewModelId, { enableValidation: changeObject.propertyValue });
                        break;
                    }
                }
            }
        };
    }
    private getEventPropertyConfig(propertyData: any, viewModelId: string): ElementPropertyConfig {
        const domService = this.domService;
        const webCmdService = this.webCmdService;
        const formBasicService = this.formBasicService;
        const eventEditorService = this.eventEditorService;
        const eventList = [
            {
                label: 'onInit',
                name: '初始化事件'
            },
            {
                label: 'afterViewInit',
                name: '视图初始化后事件'
            },
        ];
        return {
            categoryId: 'eventsEditor',
            categoryName: '事件',
            hideTitle: true,
            properties: EventsEditorFuncUtils.formProperties(eventEditorService, formBasicService, domService, webCmdService, propertyData, viewModelId, eventList),
            tabId: 'commands',
            tabName: '交互',
            setPropertyRelates(changeObject, data, parameters) {
                delete propertyData[viewModelId];
                EventsEditorFuncUtils.saveRelatedParameters(eventEditorService, domService, webCmdService, propertyData, viewModelId, eventList, parameters);
                this.properties = EventsEditorFuncUtils.formProperties(eventEditorService, formBasicService, domService, webCmdService, propertyData, viewModelId, eventList);
            }
        };
    }

    /**
     * 将变更的属性值同步到ViewModel上
     */
    private syncChangesToViewModel(viewModelId: string, changeObject: any) {
        const vm = this.domService.getViewModelById(viewModelId);
        if (!vm) {
            return;
        }
        Object.assign(vm, changeObject);
    }
}
